home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-06-07 | 34.0 KB | 1,436 lines |
- /* CEClassEditor.m
- *
- * This object controls the data of a beaker (molecules, cameras, groups etc.)
- * It is the main document of BeakerBoy and controls everything from loading to
- * setting up the browser which does most of the other work.
- *
- * For interface-info see the header file. The comments in this file mostly
- * cover only the real implementation details.
- *
- * Written by: Thomas Engel
- * Created: 23.10.1993 (Copyleft)
- * Last modified: 12.11.1994
- */
-
- #define CURRENT_VERSION 1
-
- #import <CEClassEditor.h>
- #import <CEClassEditor+FileHandling.h>
- #import <CEMethod.h>
- #import <CEBrowserCell.h>
- #import <CECellMatrix.h>
- #import <Text_MiscExtensions.h>
- #import <MiscStringArray_List.h>
- #import <MiscEmacsText.h>
-
- #import <misckit/MiscString.h>
- #import <misckit/MiscStringArray.h>
- #import <misckit/MiscSortedList.h>
-
- @implementation CEClassEditor
-
-
- + initialize
- {
- if ( self == [CEClassEditor class] )
- [CEClassEditor setVersion:CURRENT_VERSION];
-
- return self;
- }
-
- - init
- {
- return [self initFromFile:""];
- }
-
- - initFromFile:(const char *)fileName
- {
- id basename;
- id dummyFile;
-
- id cellPrototype;
-
- id headerSearchPathes;
- id sourceSearchPathes;
- id docuSearchPathes;
-
- int index; // To adjust the popUps initValue !
- id aMatrix; // Dito;
-
- self = [super init];
- if( !self ) return self;
-
- // OK. We really are an object...here we go with our init.
- // Lets load the NIB. It has set our beaker to be its window-delegate.
- // Without a NIB there will be no beaker object !
-
- if( [NXApp loadNibSection:"ClassWindow.nib" owner:self] == nil )
- {
- NXRunAlertPanel( NULL, "Couldn't load ClassWindow.nib",
- "OK", NULL, NULL );
- return nil;
- }
- // Lets setup the names.
- // We need to track all those areas where we update the text to find the
- // places where the user makes changes to the text!
-
- headerSearchPathes = [[[NXApp delegate] preferences]
- headerSearchPaths];
- sourceSearchPathes = [[[NXApp delegate] preferences]
- sourceSearchPaths];
- docuSearchPathes = [[[NXApp delegate] preferences]
- documentationSearchPaths];
-
- _docuPath = [MiscString new];
- _headerPath = [MiscString new];
- _sourcePath = [MiscString new];
-
- // On we go...
-
- dummyFile = [[MiscString new] setPath:fileName];
-
- basename = [dummyFile fileBasename];
- filename = [dummyFile pathName];
- [filename addChar:[MiscString pathSeparator]];
- [filename concatenate:basename];
- [basename free];
-
- // Get the pasteboard and ensure that nobody will see the texthandling we
- // do now.
-
- _tempPb = [Pasteboard newName:"CETempPb"];
- [self _setIsUpdatingTextViews:YES];
-
- // Now we will always refer to the file WITHOUT any extention.
- // If we are lucky we will be able to read it all..m, .h and .rtf
- // If we were able to read the file...make the view editable.
-
- [dummyFile takeStringValue:filename];
- [dummyFile cat:".h"];
- [self _try:dummyFile withAlternatives:headerSearchPathes
- forText:headerFile andGetStyle:&headerStyle andSetPath:_headerPath];
-
- // Well we really need a header file... it is crucial !
-
- if( headerStyle == CE_FILETYPE_NONE )
- {
- basename = [dummyFile fileBasename];
- NXRunAlertPanel( NULL, "Couldn't load %s.h. Not in any searchpath.",
- "Ooops", NULL, NULL,
- [basename stringValue] );
- [basename free];
- [dummyFile free];
- [[NXApp delegate] addToReleasePool:self];
- return nil;
- }
-
- // The next part is loading the source code for that class.
- // This can be either ASCII or RTF !
-
- [dummyFile takeStringValue:filename];
- [dummyFile cat:".m"];
- [self _try:dummyFile withAlternatives:sourceSearchPathes
- forText:sourceFile andGetStyle:&sourceStyle andSetPath:_sourcePath];
-
- // Now the documentation. if there is no RTF docu we should ty to find a
- // RTFD docu too !
-
- [dummyFile takeStringValue:filename];
- [dummyFile cat:".rtf"];
- [self _try:dummyFile withAlternatives:docuSearchPathes
- forText:docuFile andGetStyle:&docuStyle andSetPath:_docuPath];
-
- [dummyFile free];
-
- // Its time to check all the methods we can find.
- // NOTE: If there are No methods we will quit right here !
-
- methodList = [List new];
- if( ![self reparseMethods:self] ) return nil;
-
- // If desired we should check to documentation first...maybe we have to add
- // something before we start. But the methods have to be know !!
-
- // if( [preferences should AutoCheckDocu] )
-
- // [self checkDocumentation:self];
-
- // Now there are some window settings to be done plus adjusting the
- // browser.
-
- // First lets connect the popUps. This has to be done before the browsers
- // try to get their info.
- // Be sure we have the right initial selection inside the proper matrix !
-
- [[modePopup target] setTarget:self];
- [[modePopup target] setAction:@selector(switchToNewDisplayMode:)];
- index = [[modePopup target] indexOfItem:[modePopup title]];
-
- if( index > -1 )
- {
- aMatrix = [[modePopup target] itemList];
-
- if( ![aMatrix selectedCell] )
- [aMatrix selectCell:[[aMatrix cellList] objectAt:index]];
- }
-
- // Lets do the same for the other popup..
-
- [[secondaryModePopup target] setTarget:self];
- [[secondaryModePopup target] setAction:@selector(switchToNewDisplayMode:)];
- index = [[secondaryModePopup target] indexOfItem:[modePopup title]];
-
- if( index > -1 )
- {
- aMatrix = [[secondaryModePopup target] itemList];
-
- if( ![aMatrix selectedCell] )
- [aMatrix selectCell:[[aMatrix cellList] objectAt:index]];
- }
-
- // NOTE: We have to set the browser delegate by code because otherwise
- // we would be requested to fill the browser before the right cell
- // prototype is set (just right after loading the NIB!) !!!.
-
- cellPrototype = [[CEBrowserCell alloc] init];
-
- [cellPrototype addFixedTab:4];
- [cellPrototype addFixedTab:20];
- [cellPrototype addFixedTab:-15];
-
- [browser setMatrixClass:[CECellMatrix class]];
- [browser setCellPrototype:cellPrototype];
- [browser setTarget:self];
- [browser setAction:@selector(selectNewMethod:)];
- [browser setDoubleAction:@selector(selectNewMethod:)];
- [browser setDelegate:self];
- [browser loadColumnZero];
-
- [secondaryBrowser setMatrixClass:[CECellMatrix class]];
- [secondaryBrowser setCellPrototype:cellPrototype];
- [secondaryBrowser setDelegate:self];
- [secondaryBrowser loadColumnZero];
-
- [window setTitleAsFilename:[self filename]];
- [window setMiniwindowImage:[NXImage findImageNamed:"CESmallObjectPink"]];
-
- // Well this is ugly.
- // We should update all the view bevor it gets visible....but then we
- // have no selected cell and bang..crash..not method..and bang..not string
- // for the Text object. And the find methdo crashes...
- // [browser selectCell:[browser getLoadedCellAtRow:0 inColumn:0]];
- // somehow this doesn't work...but I don't want to waste my time.
- // Ok I fixed the selectMethod to not crash...still its not clean.
-
- [self selectNewMethod:self];
-
- // ok now we are a new document so lets become active.
-
- [self _setIsUpdatingTextViews:NO];
- _changedTexts = NO;
- [window makeKeyAndOrderFront:self];
-
- return self;
- }
-
- - free
- {
- // We do not free all the NIB objects...hmm should check that out.
-
- [window free];
- [cheatWindow free];
- [filename free];
- [_docuPath free];
- [_sourcePath free];
- [_headerPath free];
- [[methodList freeObjects] free];
-
- return [super free];
- }
-
- - window
- {
- // We have to return the main window to ensure that the right window gets
- // topped when the app decided that we should become visible.
-
- return window;
- }
-
- /*
- * Here come the methods we will implement to satisfy our window.
- * They are useful to change the inspector and handle oher tasks.
- */
-
- - reparseMethods:sender
- {
- // This is used to keep the two view up to date. Making changes to the
- // We will reset those origin pointers because copying our current text-
- // sections back would most propably destroy something!
-
- _docuOriginStart = 0;
- _docuOriginEnd = 0;
- _sourceOriginStart = 0;
- _sourceOriginEnd = 0;
- _changedTexts = NO;
-
- [self _setIsUpdatingTextViews:YES];
-
- [methodList freeObjects];
- [self _parseMethodFile];
- if( [methodList count] == 0 )
- {
- // Ooops its time to exit..ther are no method.
- // BUG: This is not a Nice way of exiting !
-
- NXRunAlertPanel( NULL, "Could not find a single method inside %s\n"\
- "Methods MUST be definined in the header file "\
- "in order to work with a class!",
- "Cancel", NULL, NULL,
- [_headerPath stringValue] );
-
- [[NXApp delegate] addToReleasePool:self];
- return nil;
- }
- // [self checkDocumentation:self];
-
- [browser loadColumnZero];
- [self _setIsUpdatingTextViews:NO];
-
- return self;
- }
-
- - save:sender
- {
- // Here we will save all the files in a stupid fashion...anyway.
- // It works for the moment.
- // We will only save file we were able to load !!
-
- id topWindow;
-
- if( ![window isDocEdited] ) return self;
-
- // Now lets be sure that ALL changes are in the main files...and
- // Nobody sees the changes going on.
- // But this should ONLY happen when the key window is or class browser.
- // We might corrupt data otherwise !!! The selection might not refer to the
- // right positions anymore !
- // We have to take care of which window was the source of the last
- // cahnges. Depening on that we will hvae to make some consitency
- // adjustment work !
-
- if( _changedTexts )
- topWindow = _changedWindow;
- else topWindow = nil;
-
- if( topWindow == window )
- [self _silentlySyncWindows];
-
- // Now if the class has been edited we will save the ASCII Header,
- // RTF source and RTF Documentaion. Quite stupid...but it works for me.
-
- [self _writeText:headerFile withStyle:headerStyle to:_headerPath];
- [self _writeText:sourceFile withStyle:sourceStyle to:_sourcePath];
- [self _writeText:docuFile withStyle:docuStyle to:_docuPath];
-
- // Ok ... well now there is nothing new here.
-
- [cheatWindow setDocEdited:NO];
- [window setDocEdited:NO];
-
- // Now tell the workspace that we did some changes..
-
- [[Application workspace] fileSystemChanged];
-
- // If we have saved from inside the cheat window we have to update the
- // main browser. Otherwise this one will no recognize the changes made.
-
- if( topWindow == cheatWindow )
- {
- [self reparseMethods:self];
- [self selectNewMethod:self];
- }
-
- return self;
- }
-
- - close:sender
- {
- // Tell both windows to go away...
- // To give feedback on which windows will dissappear we will make the
- // key first.
- // The browser window is the main window...the only one to focus at...
- // so we can close the other window if the main window is gone...
-
- [window makeKeyAndOrderFront:self];
- [window performClose:self];
- if( [window isVisible] ) return nil;
-
- // Oh...we really did close the window...the cheat window has
- // passed away during the main-close too...so we are done.
-
- return self;
- }
-
- - undo:sender
- {
- // Well sorry this is a stupid undo...it only undos alle the changes done
- // since switched to a certain method.
- // This only works if the key window is our main browser.
- // The replacement of the selection will be visiible to give visual
- // feedback that something is happening.
-
- id ourMethod;
- id focusView;
-
- if( [NXApp keyWindow] == window )
- {
- [self _setIsUpdatingTextViews:YES];
- ourMethod = selection;
- if( ourMethod != nil )
- {
- [self _showDocuForMethod:ourMethod];
- [self _showSourceForMethod:ourMethod];
- }
- if( [sourceTextView isEditable] )
- focusView = sourceTextView;
- else focusView = docuTextView;
-
- [focusView setSel:0 :0];
- [focusView scrollSelToVisible];
- _changedTexts = NO;
- [self _setIsUpdatingTextViews:NO];
- [window display];
- [cheatWindow display];
- }
- return self;
- }
-
- - resolveLock:sender
- {
- return [[NXApp delegate] showAccessHelper:self];
- }
-
- - switchToNewDisplayMode:sender
- {
- id primaryPopMatrix;
-
- // Called by the PopUp when something changes...just ask the browser..
- // who ever that may be..to load its first column.
-
- primaryPopMatrix = [[modePopup target] itemList];
-
- if( sender == primaryPopMatrix )
- {
- [browser loadColumnZero];
- [self _checkSelectionInBrowser:browser];
- }
- else [secondaryBrowser loadColumnZero];
-
- // Perhaps we don't only have the update the browser..but also
- // show the other window. this will disappear in a future release.
-
- if( sender == primaryPopMatrix &&
- [[primaryPopMatrix selectedCell] tag] == CE_BrowsePlainC )
- [self showCheatWindow:self];
-
- return self;
- }
-
- - selectNewMethodFromText:sender
- {
- const char * realMethod;
-
- // if we can't find the method..lets assume it is a new one...
- // either rename the current...or create a new one.
-
- NXRunAlertPanel( NULL, "%s\nThis acction should either rename the "\
- "current method or add a new one\n"\
- "Not yet implemented :-(",
- "Create New", "Rename Current", "Cancel",
- [sender stringValue] );
-
- // lets reset the right method string..
-
- realMethod = [selection name];
-
- if( realMethod ) [sender setStringValue:realMethod];
- return self;
- }
-
- - selectNewMethod:sender
- {
- id ourMethod;
- id focusView;
-
- // Now lets stop redraws until we have finished...looks a little better.
- // This part is a little trick because somehow I have to find the right
- // selections inside the original texts. Now the Text object is not very
- // helpful here. The find method is more then stupid.
-
- [self _setIsUpdatingTextViews:YES];
- [self _syncWindows];
-
- // During the init phase ther is no selected method inside the browser..
- // To solve that we simple take the first method we have..
-
- ourMethod = [[browser selectedCell] source];
- if( ourMethod == nil ) ourMethod = [methodList objectAt:0];
- selection = ourMethod;
-
- [selectorNameField setStringValue:[ourMethod selectorName]];
- [methodNameField setStringValue:[ourMethod name]];
-
- // Lets update the method docs/source view with the new text.
-
- [self _showDocuForMethod:ourMethod];
- [self _showSourceForMethod:ourMethod];
-
- // It is time to redraw all the fun stuff again. We will make a startup
- // selection first.
-
- if( [sourceTextView isEditable] )
- focusView = sourceTextView;
- else focusView = docuTextView;
-
- [focusView setSel:0 :0];
- [focusView scrollSelToVisible];
-
- // Now be sure that the changes really get displayed.
-
- [self _setIsUpdatingTextViews:NO];
- [self _checkSelectionInBrowser:browser];
-
- [window display];
- [cheatWindow display];
-
- // Ok here comes the test section
- return self;
- }
-
- - selectTrueLine:(int)line inSource:(BOOL)aFlag
- {
- id targetText;
-
- if( aFlag )
- {
- targetText = sourceFile;
- [self showImplementationOnly:self];
- }
- else
- {
- targetText = headerFile;
- [self showInterfaceOnly:self];
- }
- [self showCheatWindow:self];
-
- [targetText selectTrueLine:line];
- [targetText scrollSelToVisible];
-
- return self;
- }
-
- - _setIsUpdatingTextViews:(BOOL)flag
- {
- // If we have a switch of the docu update stuff...we should take
- // care that the pasteboard won't get corrupted !
- // Which means..wehn finshed with the updates...we will put back the
- // pervious pastebord contents.
-
- if( _updatingTextViews == NO &&
- flag == YES )
- {
- [window disableDisplay];
- [cheatWindow disableDisplay];
- }
-
- else if( _updatingTextViews == YES &&
- flag == NO )
- {
- [window reenableDisplay];
- [cheatWindow reenableDisplay];
- }
-
- _updatingTextViews = flag;
-
- return self;
- }
-
- - _showSourceForMethod:aMethod
- {
- // Now lets update the source view.
- // We assume that no changes get lost...so be sure to backup changes first.
- // Everything that is inside the sourceTextView will get lost.
-
- // Now if we really find the method we can show it.
-
- [self _selectSourceForMethod:aMethod];
-
- // Well...now we have a possible selection inside the original text.
- // If it is no useful selection we don't have any text...and we just mark
- // the area as useless.
-
- if( _sourceOriginStart > 0 && _sourceOriginEnd > 0 )
- {
- [sourceFile setSel:_sourceOriginStart :_sourceOriginEnd];
- [sourceFile copyTo:_tempPb];
- [sourceTextView setEditable:YES];
- [sourceTextView selectAll:self];
- [sourceTextView pasteFrom:_tempPb];
-
- [sourceTextView setMonoFont:NO];
-
- if( sourceStyle == CE_FILETYPE_ASCII ) [sourceTextView format:self];
- }
- else
- {
- [sourceTextView setEditable:YES];
- [sourceTextView selectAll:self];
- [sourceTextView delete:self];
- [sourceTextView setEditable:NO];
- }
- // We shouldn't corrupt the fonts if we can only handle ASCII !
-
- // if( sourceStyle == CE_FILETYPE_ASCII )
- // [sourceTextView setMonoFont:YES];
- // else [sourceTextView setMonoFont:NO];
-
- return self;
- }
-
- - _silentlySyncWindows
- {
- // this method silently syncs both window. You won't see any selections
- // cluttering your screen.
- // We have to reselect the source and documenation here because otherwise
- // our references won't be corret anymore !!!
-
- [window disableDisplay];
- [cheatWindow disableDisplay];
- [self _setIsUpdatingTextViews:YES];
- [self _syncWindows];
- [self _selectDocuForMethod:selection];
- [self _selectSourceForMethod:selection];
- [self _setIsUpdatingTextViews:NO];
- [cheatWindow reenableDisplay];
- [window reenableDisplay];
-
- return self;
- }
-
- - _syncWindows
- {
- // This method does sync the cheat window with the main window.
- // If there is a currently used documentation we have to copy it back
- // first !
- // After that it remarks that there are no more differneces between
- // the two views.
- // After all we DON'T trace the changes here. This is just a common
- // source part of _sliently Syncing and selecting a new method !!
-
- if( _docuOriginStart > 0 && _docuOriginEnd > 0 && _changedTexts )
- {
- [docuTextView selectAll:self];
- [docuTextView copyTo:_tempPb];
- [docuFile setSel:_docuOriginStart :_docuOriginEnd];
- [docuFile pasteFrom:_tempPb];
- [docuTextView setSel:0 :0];
- }
-
- // Same for the source code.
-
- if( _sourceOriginStart > 0 && _sourceOriginEnd > 0 && _changedTexts )
- {
- [sourceTextView selectAll:self];
- [sourceTextView copyTo:_tempPb];
- [sourceFile setSel:_sourceOriginStart :_sourceOriginEnd];
- [sourceFile pasteFrom:_tempPb];
- [sourceTextView setSel:0 :0];
- }
-
- _changedTexts = NO;
-
- return self;
- }
-
- - _showDocuForMethod:aMethod
- {
- // Now lets update the documentation view.
- // We assume that no changes get lost...so be sure to backup changes first.
- // Everything that is inside the docuTextView will get lost.
-
- // Now if we really find the method we have to remove the blakn lines and
- // set the right selection part.
-
- [self _selectDocuForMethod:aMethod];
-
- // Well...now we have a possible selection inside the original text.
- // If it is no useful selection we don't have any text...and we just mark
- // the area as useless.
-
- if( _docuOriginStart > 0 && _docuOriginEnd > 0 )
- {
- [docuFile setSel:_docuOriginStart :_docuOriginEnd];
- [docuFile copyTo:_tempPb];
- [docuTextView setEditable:YES];
- [docuTextView selectAll:self];
- [docuTextView pasteFrom:_tempPb];
- }
- else
- {
- [docuTextView setEditable:YES];
- [docuTextView selectAll:self];
- [docuTextView delete:self];
- [docuTextView setEditable:NO];
- }
- return self;
- }
-
- - showCheatWindow:sender
- {
- id aString;
- // Lets choose a defaults selection to clean up the window.
- [docuFile setSel:0 :0];
- aString = [filename fileName];
- [aString cat:"...Cheat Window"];
- [cheatWindow setMiniwindowImage:
- [NXImage findImageNamed:"ObjectPink.rtf.m.h"]];
- [cheatWindow setTitle:[aString stringValue]];
- [aString free];
-
- [cheatWindow makeKeyAndOrderFront:self];
- return self;
- }
-
- - showAllFiles:sender
- {
- NXRect bounds;
- id aView;
-
- [cheatWindow disableDisplay];
-
- // Resize the header view to some useful none-zero value.
- // This is necessary to see anything at all.
- // We take the header because it will then end up as the smallest view.
-
- aView = [[headerFile superview] superview];
- [aView getBounds:&bounds];
- [aView sizeTo:bounds.size.width :20];
-
- // Make the sourceFile and docuFile small enough..and redraw the window.
-
- aView = [[sourceFile superview] superview];
- [aView getBounds:&bounds];
- [aView sizeTo:bounds.size.width :50];
- aView = [[docuFile superview] superview];
- [aView getBounds:&bounds];
- [aView sizeTo:bounds.size.width :50];
-
- [cheatWindow disableDisplay];
- [cheatWindow display];
- return self;
- }
-
- - showDocumentationOnly:sender
- {
- [self _resizeCheatWindowFor:docuFile
- andHide:headerFile :sourceFile];
-
- return self;
- }
-
- - showInterfaceOnly:sender
- {
- [self _resizeCheatWindowFor:headerFile
- andHide:docuFile :sourceFile];
-
- return self;
- }
-
- - showImplementationOnly:sender
- {
- [self _resizeCheatWindowFor:sourceFile
- andHide:docuFile :headerFile];
-
- return self;
- }
-
- - _resizeCheatWindowFor:mainView andHide:secondView :thirdView
- {
- NXRect bounds;
- id aView;
-
- [cheatWindow disableDisplay];
-
- // Resize the main view to some useful none-zero value.
- // This is necessary to see anything at all.
-
- aView = [[mainView superview] superview];
- [aView getBounds:&bounds];
- [aView sizeTo:bounds.size.width :20];
-
- // Make the secondView and thirdView small enough..and redraw the window.
-
- aView = [[secondView superview] superview];
- [aView getBounds:&bounds];
- [aView sizeTo:bounds.size.width :0];
- aView = [[thirdView superview] superview];
- [aView getBounds:&bounds];
- [aView sizeTo:bounds.size.width :0];
-
- [cheatWindow disableDisplay];
- [cheatWindow display];
- return self;
- }
-
- - (int)browser:sender fillMatrix:matrix inColumn:(int)column
- {
- int count;
-
- // BUG: Another "bug" circumvention ??
- // I took this from the RZToDoList app. Perhaps it is quite useless...
- // I don't have the time to diddle with it..but it seams to work without
- // the next line too.
-
- [matrix renewRows:0 cols:1];
-
- // We don't use lazy browsers because it wouldn't save any space
- // (maintaining the lists twice) and it is easiers this way.
-
- if( sender == browser )
- {
- switch( [[[[modePopup target] itemList] selectedCell] tag] )
- {
- case CE_BrowseClassInfo:
- count = [self fillClassInfoIntoMatrix:matrix];
- break;
-
- case CE_BrowseInstanceVars:
- count = [self fillInstanceVarsIntoMatrix:matrix];
- break;
-
- case CE_BrowseMethods:
- count = [self fillMethodsIntoMatrix:matrix];
- break;
-
- case CE_BrowseInstanceMethods:
- count = [self fillInstanceMethodsIntoMatrix:matrix];
- break;
-
- case CE_BrowseClassMethods:
- count = [self fillClassMethodsIntoMatrix:matrix];
- break;
-
- case CE_BrowseMethodsByCategory:
- count = [self fillMethodsByCategoryIntoMatrix:matrix];
- break;
-
- case CE_BrowseDependencies:
- count = [self fillDependenciesIntoMatrix:matrix];
- break;
-
- case CE_BrowsePlainC:
- default:
- count = [self fillPlainCIntoMatrix:matrix];
- }
- }
- // Otherwise we have to fill the socond browser..
-
- else
- {
- /*
- switch( [[[[secondaryModePopup target] itemList] selectedCell] tag] )
- {
- case CE_BrowseReferences:
- count = [self fillReferencesIntoMatrix:matrix
- accordingTo:selection];
- break;
-
- case CE_BrowseHistory:
- count = [self fillHistoryIntoMatrix:matrix
- accordingTo:selection];
- break;
-
- case CE_BrowseBugs:
- default:
- count = [self fillBugsIntoMatrix:matrix
- accordingTo:selection];
- }
- */
- count = 0;
- }
-
- return count;
- }
-
- - _checkSelectionInBrowser:aBrowser
- {
- id matrix;
- int i;
- int count;
- int dummy;
-
- // Now lets see if we can make some selections. If possible the browser
- // should reflect the current selection.
-
- if( aBrowser == browser &&
- selection != nil &&
- selection != [[aBrowser selectedCell] source] )
- {
- matrix = [aBrowser matrixInColumn:0];
- [matrix getNumRows:&count numCols:&dummy];
-
- for( i=0; i<count; i++ )
- {
- if( [[matrix cellAt:i :0] source] == selection )
- {
- [matrix selectCellAt:i :0];
- [matrix scrollCellToVisible:i :0];
- break;
- }
- }
- }
- return self;
- }
-
- - (int)fillClassInfoIntoMatrix:matrix
- {
- int count;
- id theCell;
- id className;
-
- count = 0;
-
- className = [filename fileBasename];
- [matrix addRow];
- theCell = [matrix cellAt:count :0];
- [theCell setImageNamed:"ClassS" at:0];
- [theCell setText:[className stringValue] at:1 font:FONT_BOLD];
- [theCell setLeaf:YES];
- [theCell setLoaded:YES];
- [theCell setEnabled:NO];
-
- [className free];
- count++;
-
- [matrix addRow];
- theCell = [matrix cellAt:count :0];
- [theCell setImageNamed:"ProtocolS" at:0];
- [theCell setText:"<SomeProtocol>" at:1];
- [theCell setLeaf:YES];
- [theCell setLoaded:YES];
- [theCell setEnabled:NO];
-
- count++;
-
- [matrix addRow];
- theCell = [matrix cellAt:count :0];
- [theCell setImageNamed:"CategoryS" at:0];
- [theCell setText:"Archiving" at:1 font:FONT_BOLD];
- [theCell setLeaf:YES];
- [theCell setLoaded:YES];
- [theCell setEnabled:NO];
-
- count++;
-
- [matrix addRow];
- theCell = [matrix cellAt:count :0];
- [theCell setImageNamed:"CategoryS" at:0];
- [theCell setText:"Working" at:1 font:FONT_BOLD];
- [theCell setLeaf:YES];
- [theCell setLoaded:YES];
- [theCell setEnabled:NO];
-
- count++;
-
- [matrix addRow];
- theCell = [matrix cellAt:count :0];
- [theCell setImageNamed:"CategoryS" at:0];
- [theCell setText:"Private" at:1 font:FONT_BOLD];
- [theCell setLeaf:YES];
- [theCell setLoaded:YES];
- [theCell setEnabled:NO];
-
- count++;
-
- return count;
- }
-
- - (int)fillInstanceVarsIntoMatrix:matrix
- {
- int count;
- id theCell;
-
- count = 0;
-
- // BUG: There is no way to set the Tabs afterwards !!!!
-
- [matrix addRow];
- theCell = [matrix cellAt:count :0];
- [theCell clearTabs];
- [theCell addFixedTab:4];
- [theCell addProportionalTab:0.3 min:50 max:600];
- [theCell setText:"id" at:0];
- [theCell setText:"anInstance" at:1];
- [theCell setLeaf:YES];
- [theCell setLoaded:YES];
- [theCell setEnabled:NO];
-
- count++;
-
- [matrix addRow];
- theCell = [matrix cellAt:count :0];
- [theCell clearTabs];
- [theCell addFixedTab:4];
- [theCell addProportionalTab:0.3 min:50 max:600];
- [theCell setText:"id" at:0];
- [theCell setText:"secondInstance" at:1];
- [theCell setLeaf:YES];
- [theCell setLoaded:YES];
- [theCell setEnabled:NO];
-
- count++;
-
- [matrix addRow];
- theCell = [matrix cellAt:count :0];
- [theCell clearTabs];
- [theCell addFixedTab:4];
- [theCell addProportionalTab:0.3 min:50 max:600];
- [theCell setText:"int *" at:0];
- [theCell setText:"somePointer" at:1];
- [theCell setLeaf:YES];
- [theCell setLoaded:YES];
- [theCell setEnabled:NO];
-
- count++;
-
- [matrix addRow];
- theCell = [matrix cellAt:count :0];
- [theCell clearTabs];
- [theCell addFixedTab:4];
- [theCell addProportionalTab:0.3 min:50 max:600];
- [theCell setText:"is" at:0];
- [theCell setText:"thisUsefulAnyway" at:1];
- [theCell setLeaf:YES];
- [theCell setLoaded:YES];
- [theCell setEnabled:NO];
-
- count++;
-
- return count;
- }
-
- - (int)fillMethodsIntoMatrix:matrix
- {
- int i;
- int count;
- id theMethod;
- id theCell;
- id aList;
-
- aList = [MiscSortedList new];
- [aList setSortOrder:Misc_ASCENDING];
- [aList setSortEnabled:YES];
-
- for( i=0; i<[methodList count];i++ )
- [aList addObject:[methodList objectAt:i]];
-
- count = 0;
-
- for( i=0; i<[aList count]; i++ )
- {
- theMethod = [aList objectAt:i];
-
- [matrix addRow];
-
- theCell = [matrix cellAt:count :0];
- [self _fillCell:theCell forMethod:theMethod];
- [theCell setLeaf:YES];
- [theCell setLoaded:YES];
-
- count++;
- }
- [aList free];
- return count;
- }
-
- - (int)fillInstanceMethodsIntoMatrix:matrix
- {
- int i;
- int count;
- id theMethod;
- id theCell;
- id aList;
-
- aList = [MiscSortedList new];
- [aList setSortOrder:Misc_ASCENDING];
- [aList setSortEnabled:YES];
-
- for( i=0; i<[methodList count];i++ )
- [aList addObject:[methodList objectAt:i]];
-
- count = 0;
-
- for( i=0; i<[methodList count]; i++ )
- {
- theMethod = [aList objectAt:i];
-
- if( [theMethod isInstanceMethod] )
- {
- [matrix addRow];
-
- theCell = [matrix cellAt:count :0];
- [self _fillCell:theCell forMethod:theMethod];
- [theCell setLeaf:YES];
- [theCell setLoaded:YES];
-
- count++;
- }
- }
- [aList free];
- return count;
- }
-
- - (int)fillClassMethodsIntoMatrix:matrix
- {
- int i;
- int count;
- id theMethod;
- id theCell;
- id aList;
-
- aList = [MiscSortedList new];
- [aList setSortOrder:Misc_ASCENDING];
- [aList setSortEnabled:YES];
-
- for( i=0; i<[methodList count];i++ )
- [aList addObject:[methodList objectAt:i]];
-
-
- count = 0;
-
- for( i=0; i<[methodList count]; i++ )
- {
- theMethod = [aList objectAt:i];
-
- if( ![theMethod isInstanceMethod] )
- {
- [matrix addRow];
-
- theCell = [matrix cellAt:count :0];
- [self _fillCell:theCell forMethod:theMethod];
- [theCell setLeaf:YES];
- [theCell setLoaded:YES];
-
- count++;
- }
- }
- [aList free];
- return count;
- }
-
- - (int)fillMethodsByCategoryIntoMatrix:matrix
- {
- int i;
- int count;
- id theMethod;
- id theCell;
- id className;
-
- count = 0;
-
- className = [filename fileBasename];
- [matrix addRow];
- theCell = [matrix cellAt:count :0];
- [theCell setImageNamed:"ClassS" at:0];
- [theCell setText:[className stringValue] at:1 font:FONT_BOLD];
- [theCell setLeaf:YES];
- [theCell setLoaded:YES];
- [theCell setEnabled:NO];
-
- [className free];
- count++;
-
- // Now add all the methods...unsorted..
-
- for( i=0; i<[methodList count]; i++ )
- {
- theMethod = [methodList objectAt:i];
-
- [matrix addRow];
-
- theCell = [matrix cellAt:count :0];
- [self _fillCell:theCell forMethod:theMethod];
- [theCell setLeaf:YES];
- [theCell setLoaded:YES];
-
- count++;
- }
- return count;
- }
-
- - (int)fillDependenciesIntoMatrix:matrix
- {
- int count;
- id theCell;
-
- count = 0;
-
- [matrix addRow];
- theCell = [matrix cellAt:count :0];
- [theCell setText:"<appkit/appkit.h>" at:1];
- [theCell setLeaf:YES];
- [theCell setLoaded:YES];
- [theCell setEnabled:NO];
-
- count++;
-
- [matrix addRow];
- theCell = [matrix cellAt:count :0];
- [theCell setText:"<misckit/misckit.h>" at:1];
- [theCell setLeaf:YES];
- [theCell setLoaded:YES];
- [theCell setEnabled:NO];
-
- count++;
-
- [matrix addRow];
- theCell = [matrix cellAt:count :0];
- [theCell setText:"\"nothing/works.h\"" at:1];
- [theCell setLeaf:YES];
- [theCell setLoaded:YES];
- [theCell setEnabled:NO];
-
- count++;
-
- return count;
- }
-
- - (int)fillPlainCIntoMatrix:matrix
- {
- return [self fillMethodsByCategoryIntoMatrix:matrix];
- }
-
- - _fillCell:theCell forMethod:aMethod
- {
- if( [aMethod isInstanceMethod] )
- [theCell setImageNamed:"InstanceMethodS" at:0];
- else [theCell setImageNamed:"ClassMethodS" at:0];
-
- [theCell setText:[aMethod selectorName] at:1];
- [theCell setSource:aMethod];
-
- // Now set the infos we need for dragging.
-
- [theCell setDraggingSource:aMethod at:0];
-
- return self;
- }
-
- - (int)fillReferencesIntoMatrix:matrix accordingTo:theSelection
- {
- return 0;
- }
-
- - (int)fillHistoryIntoMatrix:matrix accordingTo:theSelection
- {
- return 0;
- }
-
- - (int)fillBugsIntoMatrix:matrix accordingTo:theSelection
- {
- return 0;
- }
-
- - textDidChange:sender
- {
- // Here we will make both windows as edited. This is for checking
- // before saving.
- // But if we are updating the views from the program we won't say that
- // this are real changes. Only user changes count !!
- // For internal use we are tracking the "real"changes since the last
- // sync between the two windows.
-
- if( sender != docuTextView &&
- sender != sourceTextView &&
- sender != docuFile &&
- sender != headerFile &&
- sender != sourceFile ) return self;
-
- // well only if one of the the relevant texts did send the msg we
- // will procede.
-
- if( _updatingTextViews == NO &&
- _changedTexts == NO )
- {
- [cheatWindow setDocEdited:YES];
- [window setDocEdited:YES];
- _changedTexts = YES;
- _changedWindow = [sender window];
- }
-
- return self;
- }
-
- - textDidGetKeys:sender isEmpty:(BOOL)flag
- {
- // This is for tracing down changes inside the window and highlighing the
- // character pairs.
-
- [self textDidChange:sender];
-
- // Now if someone typed a character that should have a corresponding pair
- // we will highlight temp here.
-
- return self;
- }
-
- - _highlightPrevious:(char *)aString inView:aText
- {
- // this is for highlighing the character pairs.
- // The current char and his counter part get highlighted if is is found
- // If not we will Ping loud.
-
- NXSelPt currentFrom;
- NXSelPt currentTo;
- NXSelPt from;
- NXSelPt to;
- BOOL gotIt;
-
- [aText getSel:¤tFrom :¤tTo];
- gotIt = [aText findText:aString
- ignoreCase:NO backwards:YES wrap:NO];
-
- if( gotIt )
- {
- [aText getSel:&from :&to];
- [aText setSel:currentFrom.cp-1 :currentFrom.cp];
- // wait( 1 );
- [aText setSel:from.cp :to.cp];
- }
- else // NXBeep();
-
- [aText setSel:currentFrom.cp :currentTo.cp];
- return self;
- }
-
- - textShouldPerformCompletion:sender
- {
- id nameArray;
- id aMethod;
- id aString;
- id stringToFind;
- int i;
- int foundItems;
- int firstMatch;
-
- // Ok..only inside the methodField we will do completion
-
- if( [sender delegate] != methodNameField ) return nil;
-
- // Now get the string and find what we need.
-
- stringToFind = [MiscString newWithString:[methodNameField stringValue]];
- nameArray = [MiscStringArray new];
-
- for( i=0; i<[methodList count]; i++ )
- {
- aMethod = [methodList objectAt:i];
- [nameArray addString:[aMethod selectorName]];
- [nameArray addString:[aMethod name]];
- }
- // Now cont the hits...
-
- foundItems = 0;
- firstMatch = -1;
-
- for( i=0; i<[nameArray count]; i++ )
- {
- aString = [nameArray objectAt:i];
- if( [aString spotOfString:stringToFind caseSensitive:YES] == 0 )
- {
- foundItems++;
- if( firstMatch == -1 ) firstMatch = i;
- }
- }
- // Now what have we found.. if there are more then one don't do anything.
-
- if( foundItems == 1 )
- [methodNameField setStringValue:[nameArray stringAt:firstMatch]];
-
- // Free it all! We hope that the Array frees the
-
- [stringToFind free];
- [nameArray free];
- return self;
- }
-
- - windowDidBecomeKey:sender
- {
- // Lets look only at the window. Depending on which window has become key
- // We have to make some updates between the two views.
-
- if( _changedTexts == NO ) return self;
-
- // If the sender is the window where we did make the last changes there
- // is no need to do some updates at all. Just leave it as it is.
-
- if( sender == _changedWindow ) return self;
-
- if( sender == window )
- {
- [self reparseMethods:self];
- [self selectNewMethod:self];
- }
-
- if( sender == cheatWindow )
- [self _silentlySyncWindows];
-
- return self;
- }
-
- - windowWillClose:sender
- {
- // Lets save the contents if the user wants it and free ourself.
-
- int result;
-
- if( sender != window ) return self;
-
- // Oh...looks like somebody wants to close the main window...
- // Lets check if we have something to save.
-
- if( [window isDocEdited] )
- {
- result = NXRunAlertPanel( "Close", "Save changes to %s?",
- "Save", "Don't Save", "Cancel",
- [filename stringValue] );
-
- if( result == NX_ALERTOTHER )
- return nil;
-
- else if( result == NX_ALERTDEFAULT )
- [self save:self];
- }
- // We will tell the window that they have to interesting information
- // anymore. This is because the app checks for these infos before quitting.
- // And if we decide "Don't save"...this should be done correct.
-
- [window setDocEdited:NO];
- [cheatWindow setDocEdited:NO];
- [cheatWindow deminiaturize:self];
- [cheatWindow performClose:self];
-
- // Its time to go....
-
- [[NXApp delegate] addToReleasePool:self];
- return self;
- }
-
- @end
-
- /*
- * History: 13.01.95 Buh
- *
- *
- * Bugs: - ...
- */